import javax.imageio.stream.ImageInputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Scanner;
import java.lang.reflect.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * 反射，枚举，lambda表达式
 */

// 反射:程序运行前检查，访问和修改类和接口，方法，字段的机制。
    class Student{
        private int age;
        public String name = "bit";

        public Student(){
            System.out.println("Student()");
        }
        public Student(int age ,String name){
            this.age = age;
            this.name = name;
            System.out.println("Student(int age,String name");
        }

        public void eat(){
            System.out.println("I am eating");
        }

        public void sleep(){
            System.out.println("I am sleep");
        }

        private void running(int time){
            System.out.println("I am running. Time: " + time);
        }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }


    public static void main(String[] args) {
        //1.通过getClass()方法获取对象
        Student s = new Student();
        Class  c = s.getClass();

        //2.通过类名.class方式获取
        //每一个类中都存在一个隐式的class记录类的对象
        Class c1 = Student.class;

        //3.通过Claas.forname(类的全路径)方法获取
        Class c2 = null;
        try{
            c2 = Class.forName("Student");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }

        System.out.println(c.equals(c1));
        System.out.println(c.equals(c2));
        System.out.println(c1.equals(c2));
    }
}


class reflectClassDemo{

        //创建对象
    public static void classNewInstance(){
        //会报异常
        try {
            //创建反射类相关的Class引用
            Class<?> classStudent = Class.forName("Student");
            //使用Class类型引用中的newInstance()方法
            Object objectStudent = classStudent.newInstance();
            //向下转型
            Student student = (Student) objectStudent;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    //获取私有的构造方法
    public static void classNewConstructor(){

        //捕获异常
        try{
            //1.获取class类的引用
            Class<?> classConstructor = Class.forName("Student");
            //2.获取构成类引用,指定参数的构造
            Constructor<?> studentConstructor = classConstructor.getDeclaredConstructor(int.class,String.class);
            //3.设置
            studentConstructor.setAccessible(true);
            //4.创建实例
            Object objectConstructor = studentConstructor.newInstance(15,"aoliu");
            //5.向下转型
            Student s = (Student)objectConstructor;
            System.out.print("构造方法：" + s) ;

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //反射私有的字段
    public static void reflectPrivateFiled(){
        try{
            //1.获取反射类的对象
            Class<?> reflectClassStudent = Class.forName("Student");
            //2.获取字段类引用
            Field field = reflectClassStudent.getDeclaredField("age");
            //3.创建新的实例
            Object object = reflectClassStudent.newInstance();
            Student student = (Student)object;
            //4.将私有属性设置可修改的
            field.setAccessible(true);
            //5.修改私有的字段
            field.set(student,12);
            //6.输出修改后的结果
            System.out.println("修改后的结果：" + student);

        }catch(Exception e){
            e.printStackTrace();
        }
    }
    //获取私有的方法
    public static void reflectPrivateMethod(){
        try {
            //1.创建Class类的引用
            Class<?> classMethod = Class.forName("Student");
            //2.创建Methoed类的引用
            Method method = classMethod.getDeclaredMethod("running",int.class);
            //3.设置为可修改
            method.setAccessible(true);
            //4.创建实例
            Object object = classMethod.newInstance();
            Student student = (Student)object;
            //5.调用私有的方法:参数是对象引用，和私有方法的参数列表
            method.invoke(student,1);

        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //修改原有的成员变量
        reflectClassDemo.classNewConstructor();
        reflectClassDemo.reflectPrivateFiled();
        reflectClassDemo.reflectPrivateMethod();
    }
}

//枚举的使用
enum TestEnum {
    //红黄绿
    //red, yellow, greed;

    //枚举的构造方法默认是私有的
    Red("red",1),Greed("greed",2),Yellow("yellow",3);

    private TestEnum(String name,int key){
        this.name = name;
        this.key = key;
    }

    public String name;
    public int key;

    //获取成员值
    public static TestEnum getEnum(int key){
        TestEnum ret;
        for(TestEnum r : TestEnum.values()){
            if(r.key == key){
               return r;
            }
        }
        return null;
    }

    //通过反射来获取枚举的构造方法
    public static void ReflectPrivateConstructor(){
        try{
            //1.获取Class类的引用
            Class<?> classT = Class.forName("TestEnum");
            //2.获取Constructor的引用
            Constructor<?> constructor = classT.getDeclaredConstructor(String.class,int.class,String.class,int.class);
            //3.设置
            constructor.setAccessible(true);
            //4.创建实例
            Object o = constructor.newInstance("父类参数",666,"White",4);
            TestEnum t = (TestEnum) o;
            //5.测试
            System.out.println("修改后的枚举常量" + t);


        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //报异常;.NoSuchMethodException: T
        TestEnum.ReflectPrivateConstructor();
        //将参数修改后还是会报异常
        //err：IllegalArgumentException
        /**
         *  if ((clazz.getModifiers() & Modifier.ENUM) != 0)
         *             throw new IllegalArgumentException("Cannot reflectively create enum objects");
         *  ENUM           0x00004000
         *  public native int getModifiers();
         */

    }

    public static void main4(String[] args) {
        System.out.println(TestEnum.getEnum(2));
    }

    public static void main3(String[] args) {
        //compare方法
        TestEnum t1 = TestEnum.Red;
        TestEnum t2 = TestEnum.Greed;

        System.out.println(t1.compareTo(t2));
        System.out.println(t1.compareTo(TestEnum.Red));
        System.out.println(t2.compareTo(TestEnum.Greed));
    }
    public static void main2(String[] args) {
        //将枚举成员转变为数组
        TestEnum[] test = TestEnum.values();
        for (int i = 0; i < test.length; i++) {
            System.out.println(test[i] + "索引下标：" + test[i].ordinal());
        }
        System.out.println("===============");
        //将字符串转换为枚举实例
        System.out.println(TestEnum.valueOf("greed"));
    }
    public static void main1(String[] args) {
        TestEnum t = TestEnum.Red;
        switch(t)
        {
            case Red: {
                System.out.println("红色");
                break;
            }
            case Yellow: {
                System.out.println("黄色");
                break;
            }
            case Greed:
                System.out.println("绿色");
                break;
        }
    }
}

//写一个单例模式
class Singleton{
   private  volatile static Singleton uniqueInstance;
   public void Singleton(){}

    public static Singleton getInstance(){
       if(uniqueInstance == null){
           synchronized (Singleton.class){
               if(uniqueInstance == null){
                   return new Singleton();
               }
           }
       }
       return uniqueInstance;
    }
}
//静态内部类实现单例模式
class Singleton1{
        private Singleton1(){}

    public static Singleton1 getInstance(){
            return UserSingletonInstance.Instance;
    }
    private static class UserSingletonInstance{
            public static final Singleton1 Instance = new Singleton1();
    }

    public static void main(String[] args) {
        Singleton1 s1 = Singleton1.getInstance();
        Singleton1 s2 = Singleton1.getInstance();
        System.out.println("实例化的两个实例是否相同：" + s1.equals(s2));
    }
}

//使用枚举实现单例模式
enum Test{
        Instance;
        public static Test getInstance(){
            return Instance;
        }

    public static void main(String[] args) {
        Test t1 = Test.getInstance();
        Test t2 = Test.getInstance();
        System.out.println(t1 == t2);
    }
}

/**
 * lambda表达式：可以通过表达式表示一个功能性的接口
 * 表现形式通常为（参数列表） -> {可以是一个值，也可以是一个表达式}
 */

/**
 * 函数式接口：接口中只有一个抽象的方法
 * 符号：@FunctionalInterface
 */
@FunctionalInterface
interface NotParameterNoReturn{
    void test();
}
@FunctionalInterface
interface OneParameterNoReturn{
    void test(int x);
}
@FunctionalInterface
interface MornParameterNoReturn{
    void test(int a,int b);
}
@FunctionalInterface
interface NotParameterReturn{
    int test();
}
@FunctionalInterface
interface OneParameterReturn{
    int test(int x );
}
@FunctionalInterface
interface MornParameterReturn{
    int test(int x,int y);
}


@FunctionalInterface
interface Sort{
    int  sort(int a,int b);
}
class tsetDemo{

    //map中的接口
    public static void main(String[] args) {
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"hello");
        map.put(2,"bit");
        map.put(3,"hello");
        map.put(4,"bit");

        map.forEach(new BiConsumer<Integer,String>(){
            @Override
            public void accept(Integer v,String k){
                System.out.println(v + "->" + k);
            }
        });
        System.out.println();
        //使用lambda表达式
        map.forEach((v,k) ->{
            System.out.println(v + "->" + k);
        });

    }

    //list中的接口
    public static void main6(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("bit");
        list.add("hello");
        list.add("lambda");
        //使用排序方法
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String str1,String str2){
                return str1.compareTo(str2);
            }
        });
        System.out.println(list);

        //使用lambda表达式实现的比较器
        list.sort((s1,s2) ->{
            return s1.compareTo(s2);
        });
        System.out.println(list);

    }

    //collection接口
    public static void main5(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("bit");
        list.add("hello");
        list.add("lambda");
        //使用foreach方法
        list.forEach(new Consumer<String>() {
          @Override
          public void accept(String str) {
              System.out.print(str + " ");
          }
        });
        System.out.println();
        //使用lambda表达式
        //带一个参数没有返回值的方法
        list.forEach(s ->{
            System.out.print(s + " ");
        });

    }

   //变量捕获:即使不带参数，可以使用其他方法中的变量
   public static void main4(String[] args) {
       int a = 100;
       NotParameterNoReturn n = () ->{
           System.out.print("捕获到了变量a：" + a );
       };
       n.test();
   }

    public static void main3(String[] args) {
        //有返回值没有参数的方法
        NotParameterReturn n1 = () ->{
            return 1;
        };
        System.out.println("返回值为：" + n1.test());
        //有返回值有一个参数的方法
        OneParameterReturn o1 = (a) ->{
          return a * 2;
        };
        System.out.println("返回值是参数的两倍："  + o1.test(1));

        //多个参数有返回值的方法
        MornParameterReturn m1 = (a,b) ->{
            return a + b;
        };
        System.out.println("返回值是参数的和：" + m1.test(10 , 20));

    }


    public static void main2(String[] args) {
        //没有返回值，带参数的lambda表达式
        OneParameterNoReturn o1 = (a) ->{
            System.out.println("带一个参数的没有返回值的方法:" + 1);
        };
        o1.test(1);
        MornParameterNoReturn m1 = (a,b) -> {
            System.out.println("多个参数没有返回值的方法：" + (a + b));
        };
        m1.test(10,20);
    }

    public static void main1(String[] args) {
        //lambda表达式就是匿名内部类实现接口的简化
        //没有调用lambda表达式的使用
        NotParameterNoReturn notParameterNoReturn = new NotParameterNoReturn() {
            @Override
            public void test() {
                System.out.println("重写的匿名内部类实现接口的方法");
            }
        };
        notParameterNoReturn.test();

        //使用lambda表达式的方法
        NotParameterNoReturn notParameterNoReturn1 = () -> {
            System.out.println("使用lambda表达式后重写的接口的test（）方法！！！");
        };
        notParameterNoReturn1.test();
    }
}





